﻿package ascript
{
	//#########################
	// Header Includes
	//#########################
	import starling.display.Sprite;
	import starling.events.Event;
	import flash.utils.getTimer;
	
	//#########################
	// Class Declaration
	//#########################
	public class Game extends Sprite
	{
		//=========================
		// Variables
		//=========================
		// Publics
		public var gameLevel:GameLevel;
		public var gameUI:GameUI;
		public var gameSound:GameSound;
		
		// Privates
		private static var gameSingleton:Game;
		private var gameIsPaused:Boolean;
		private var gameTime:int;
		private var gameTimePaused:int;
		private var gameTimeLast:int;
		
		//=========================
		// Initialization
		//=========================	
		public function Game():void
		{
			// Game is treated as a singleton, so it can only be instanced once
			if ( gameSingleton == null )
			{
				gameSingleton = this;
				
				// Add Listeners
				addEventListener( Event.ADDED_TO_STAGE, stageAddedGame );
			}
			else
			{
				throw Error( "Game Singleton can only be instanced once!" );
			}
		}
			
		private function stageAddedGame( tEvent:Event ):void
		{
			// Load Level
			setLevelGame( 0 );
			
			// Add Listeners
			addEventListener( Event.REMOVED_FROM_STAGE, stageRemovedGame );
			addEventListener( Event.ENTER_FRAME, tickGame );
		}
		
		private function stageRemovedGame( tEvent:Event ):void
		{
			// Remove Listeners
			removeEventListener( Event.REMOVED_FROM_STAGE, stageRemovedGame );
			removeEventListener( Event.ENTER_FRAME, tickGame );
		}
		
		//=========================
		// Mutators
		//=========================
		public static function get game():Game
		{
			return gameSingleton;
		}
		
		public function get time():int
		{
			return gameTime;
		}
		
		public function get timePaused():int
		{
			return gameTimePaused;
		}
		
		public function get paused():Boolean
		{
			return gameIsPaused;
		}
		
		public function setPausedGame( tIsPaused:Boolean ):void
		{
			if ( gameIsPaused != tIsPaused )
			{
				// Apply
				gameIsPaused = tIsPaused;
				gameUI.pauseObject( tIsPaused );
				gameLevel.pauseObject( tIsPaused );
				gameSound.pauseSound( tIsPaused );
				
				// Calculate pause time if unpaused
				if ( !tIsPaused )
				{
					gameTimePaused = getTimer() - gameTime;
				}
			}
		}
		
		public function setUIGame( tUI:String ):void
		{
			if ( gameUI == null || gameUI.name != tUI )
			{
				gameUI = new GameUI( this, tUI );
			}
		}
		
		public function setSoundGame( tSound:String ):void
		{
			if ( gameSound == null || gameSound.soundName != tSound )
			{
				// Destroy any previous
				if ( gameSound != null )
				{
					gameSound.destroySound();
					gameSound = null;
				}
				
				// Create new
				gameSound = new GameSound( this, tSound );
			}
		}
		
		public function setLevelGame( tLevelNumber:uint ):void
		{
			if ( gameLevel == null || gameLevel.name != tLevelNumber )
			{
				gameLevel = new GameLevel( this, tLevelNumber );
			}
		}
		
		//=========================
		// Tick
		//=========================
		private function tickGame( tEvent:Event ):void
		{
			// Update objects only if unpaused
			if ( timePaused )
			{
				gameTime = getTimer() - gameTimePaused;
				
				gameLevel.updateObject( this, ( gameTime - gameTimeLast ) );
				gameUI.updateObject( this, ( gameTime - gameTimeLast ) );
				
				gameTimeLast = gameTime;
			}
			
			// Update Sound
			gameSound.updateSound( this, gameTime, getTimer() );
		}
	}
}